import axios from 'axios'

import {flightEngine} from './flightSearch.js'
import {verifiyEfficiency} from "../vm/monitor.js";
import {TimeoutError} from "../utils/errors.js";


/**
 *
 * @param {requestParam} flightParams
 * @param depFlight
 * @returns {boolean}
 */
function compareFlight(flightParams, depFlight) {
    if (depFlight.legs.some(item => flightParams.excludeCarriers.includes(item.airlineCode))) {
        return true;
    }
    return false;
};
function compareFlights(flightParams, depFlight, outItoa,outTopN,log) {
    if (outItoa >= outTopN) return { status: 'skipped', reason: 'outItoa >= outTopN' };;
    if (depFlight.legs.some(item => flightParams.excludeCarriers.includes(item.airlineCode))){
        log.info('去程排除：', depFlight.legs.map(flight => flight.airlineCode));
        return { status: 'skipped', reason: 'excluded carrier' };
    }
    log.info('去程处理：', depFlight.legs.map(flight => flight.airlineCode));
    return {status: 'fulfilled',reason: 'success'}
}
/**
 * 查询
 * @param {requestParam} flightParams
 * @param {flightInfo} depFlight
 * @param {Logger} log
 * @param {flightLeg} e
 * @returns {Promise<*>}
 */

function flightKeysContains(flightParams, depFlight, log) {
    // 判断是否包含在必须爬的数据里
    //  判断是否有flightKeys

    if (flightParams.flightKeys.length !== 0) {
        let depTime = "" + depFlight.departureTime.getMonth() + depFlight.departureTime.getDate() + depFlight.departureTime.getHours() + depFlight.departureTime.getMinutes();
        let landTime = "" + depFlight.landingTime.getMonth() + depFlight.landingTime.getDate() + depFlight.landingTime.getHours() + depFlight.landingTime.getMinutes();
        let flightNumber = depFlight.legs.map(leg => leg.airlineCode + leg.flightNumber).join("/");
        let flightTime = depTime + "/" + landTime;
        // log.info(`${depFlight.departureAirportCode + "/" + depFlight.landingAirportCode} ${flightNumber} ${depFlight.minimumPrice} ${flightTime}`)
        // 有判断是否有flightKeys 判断是不是要的航班
        let compareKeys = flightParams.flightKeys.filter(e => {
            // 组合多重航段的航班号
            // 如果起降机场不一致就跳过
            if (!(depFlight.departureAirportCode + "/" + depFlight.landingAirportCode) === e.airport) {
                return false;
            }
            // 如果价格不一致 跳过
            if (!depFlight.minimumPrice === e.cast) {
                return false;
            }
            // 航班号不一致
            if (!flightNumber.includes(e.flightNo)) {
                return false;
            }
            if (!(flightTime) === e.time) {
                return false;
            }
            // 判断是否在flightKeys里
            return true;
        });
        // 如果在 就返回false 继续
        if (compareKeys.length > 0) {
            return false;
        }
        return true;
    }
    return true;
}

/**
 * 查询
 * @param {requestParam} flightParams
 * @param {Logger} log
 * @returns {Promise<*>}
 */

export async function query(flightParams, log) {
    // 初始化一个实例
    let startTime = Date.now();
    if (flightParams.timeout === null || flightParams.timeout === undefined) {
        flightParams.timeout = 180000
    }
    let timeoutMills = flightParams.timeout - 6000;
    // 执行结果
    let res = {};
    let resList = [];
    // 总ota
    let channels = new Set()
    // 初始化请求示例
    let engine = new flightEngine(flightParams, log, startTime, timeoutMills);
    let __r = await engine.getParamInfo();
    log.info("request param bl", engine.bl);
    res.abortId = engine.abortId;
    try {
        // 先根据名称搜索一下
        flightParams.startCityParam = await engine.searchByName(flightParams.startCityName, flightParams.startCity, log);
        flightParams.endCityParam = await engine.searchByName(flightParams.endCityName, flightParams.endCity, log);
        // if (searchResult && searchResult.length > 0) {
        //     res = searchResult;
        //     channels.add('ota');
        // }
        let shoppingResults = null;
        for (let i = 0; i < 3; i++) {

            try {
                // --------------molia--------------
                shoppingResults = await engine.getShoppingResults(flightParams, log);
                // shoppingResults = await engine.getShoppingResults(flightParams, log);
                break
            } catch (e) {
                log.error('querying error times ', i, e.stack)
                continue
            }

        }
        if (shoppingResults === null) {
            throw Error('3times cannot search shopping list break;')
        }
        res['data'] = shoppingResults.text
        log.info(`query flight res best: ${shoppingResults.data.bestFlightList.length} common: ${shoppingResults.data.commonFlightList.length}`);
        let subData = [];
        res.subData = subData;
        // try {
        //
        //
        // } catch (e) {
        //     log.error('querying error ', e.message)
        // }


        //先单程
        if (!flightParams.isTripType) {
            let topN = flightParams.topN;
            let auto = 0;

            let bestFlightList = shoppingResults.data.bestFlightList;
            log.info(`oneway flights best count: ${bestFlightList.length}`);
            if (bestFlightList != null) {
                for (let j = 0; j < bestFlightList.length; j++) {
                    let depFlight = bestFlightList[j];
                    if (compareFlight(flightParams, depFlight) || auto >= topN) {
                        log.info('第二页面 不要：',depFlight.legs.map(flight => flight.airlineCode))
                        continue;
                    }
                    log.info('第二页面  要：',depFlight.legs.map(flight => flight.airlineCode))
                    log.info(`oneway best start query flight topN ${topN} out ${auto}`);
                    if (Date.now() - startTime > timeoutMills) {
                        log.error("timeout");
                        res.channels = Array.from(channels);
    res.functionCallCount = engine.functionCallCount

                        return res;
                    }
                    try{
                        let bookingResult = await engine.getBookingResult(flightParams, depFlight, null);
                        for (let channelPrice of bookingResult.data.channelPrices) {
                            channels.add(channelPrice.name);
                        }
                        subData.push(bookingResult.text);
                        resList.push(bookingResult.data);
                        auto++;
                    }catch (e){
                        if (e instanceof TimeoutError){
                            res.channels = Array.from(channels);
                                res.functionCallCount = engine.functionCallCount

                            return res;
                        }
                    }
                }
            }

            let commonFlights = shoppingResults.data.commonFlightList;
            log.info(`oneway flights common count: ${commonFlights.length}`);
            if (commonFlights != null) {
                for (let j = 0; j < commonFlights.length; j++) {
                    let depFlight = commonFlights[j];
                    if ((auto >= topN && flightKeysContains(flightParams, depFlight, log)) || compareFlight(flightParams, depFlight)) {
                        log.info('第二页面 不要：',depFlight.legs.map(flight => flight.airlineCode))
                        continue;
                    }
                    log.info('第二页面  要：',depFlight.legs.map(flight => flight.airlineCode))
                    log.info(`oneway common start query flight topN ${topN} out ${auto} now ${j}`);
                    if (Date.now() - startTime > timeoutMills) {
                        log.error("timeout");
                        res.channels = Array.from(channels);
                            res.functionCallCount = engine.functionCallCount


                        return res;
                    }
                    try{
                        let bookingResult = await engine.getBookingResult(flightParams, depFlight, null);
                        for (let channelPrice of bookingResult.data.channelPrices) {
                            channels.add(channelPrice.name);
                        }
                        subData.push(bookingResult.text);
                        resList.push(bookingResult.data);
                        auto++;
                    }catch (e){
                        if (e instanceof TimeoutError){
                            res.channels = Array.from(channels);
                                res.functionCallCount = engine.functionCallCount

                            return res;
                        }
                    }
                }
            }

            log.info(`channels n: ${channels.size} ${Array.from(channels).toString()}`);
            res.channels = Array.from(channels);
            // MetricsService.addCounter(channels.length);
                res.functionCallCount = engine.functionCallCount

            return res;
        }
        // 往返了
        else {
            let outTopN = flightParams.depOfficialTopN;
            let rtOfficialTopN = flightParams.rtOfficialTopN;
            let outItoa = 0;
            log.info(' 第一次请求 : ', 'bestFlightList:  ', shoppingResults.data.bestFlightList.length, '   commonFlightList:  ', shoppingResults.data.commonFlightList.length)
            const bestFlightList = shoppingResults.data.bestFlightList;
            const commonFlights = shoppingResults.data.commonFlightList;
            log.info(`rt flights best count: ${bestFlightList.length}`);
            const toRes = [];
            res.subData = toRes;
            async function processWithConcurrency(tasks, concurrency = 1) {
                const results = [];
                const executing = new Set();

                for (const task of tasks) {
                    if (executing.size >= concurrency) {
                        // 等待任意一个任务完成
                        await Promise.race(executing);
                    }

                    const p = Promise.resolve().then(() => task())
                        .then(result => {
                            // Ensure we always have a consistent return format
                            if (!result || typeof result !== 'object') {
                                return {
                                    type: 'unknown',
                                    data: result
                                };
                            }
                            return result;
                        });

                    executing.add(p);
                    p.then(() => executing.delete(p));
                    results.push(p);
                }

                return Promise.allSettled(results);
            }

            async function first_page_get_data(AllFlightList) {
                let first_best_list = []
                if (AllFlightList) {
                    // 修改后的处理逻辑
                    const tasks = [];
                for (let x = 0; x < AllFlightList.length && outItoa < outTopN; x++) {
                    const depFlight = AllFlightList[x];

                    // 先进行所有条件检查
                    if (outItoa >= outTopN) break; // 直接终止循环

                    if (depFlight.legs.some(item => flightParams.excludeCarriers.includes(item.airlineCode))) {
                        // console.log('----返程排除 : ', depFlight.legs.map(flight => flight.airlineCode));
                        // Push an alert object instead of the actual task
                        tasks.push(async () => {
                            return {
                                type: 'excluded',
                                flight: depFlight,
                                reason: 'excluded_carrier',
                                airlines: depFlight.legs.map(flight => flight.airlineCode)
                            };
                        });
                        continue;
                    }

                    // 只有符合条件的才会被推入正常的 tasks
                    // console.log('----返程处理 : ', depFlight.legs.map(flight => flight.airlineCode));
                    log.info('返程处理 : ', depFlight.legs.map(flight => flight.airlineCode));
                    outItoa++;

                    tasks.push(async () => {
                        try {
                            const result = await engine.getShoppingReturnResults(flightParams, depFlight, true);
                            return {
                                type: 'valid',
                                data: result,
                                flight: depFlight
                            };
                        } catch (error) {
                            return {
                                type: 'error',
                                error: error,
                                flight: depFlight
                            };
                        }
                    });
                }

                    first_best_list = await processWithConcurrency(tasks);
                    // console.log('------------ 处理完成 ------------ outItoa = ', outItoa);
                    if (Date.now() - startTime > timeoutMills) {
                        res.channels = Array.from(channels);
                        res.functionCallCount = engine.functionCallCount;
                        return res;
                    }

                    for (let j = 0; j < first_best_list.length; j++) {
                        const result = first_best_list[j];
                        const shoppingReturnResults = result.value;
                        if (shoppingReturnResults.type !== 'valid'){
                            continue;
                        }
                        const shoppingReturnResult = shoppingReturnResults.data
                        const returnData = {};
                        returnData.data = shoppingReturnResult.text;
                        const rtBookingList = [];
                        returnData.subData = rtBookingList;
                        let rtItoa = 0;
                        // 处理AllFlightList
                        const returnBestList = shoppingReturnResult.data?.bestFlightList || [];
                        const returnCommonLists = shoppingReturnResult.data?.commonFlightList || [];

                        async function deal_with(FlightList, returnList) {
                            let bestPromises = [];
                            for (let y = 0; y < returnList.length && rtItoa < rtOfficialTopN; y++) {
                                const returnBestList = returnList[y];
                                if (rtItoa >= rtOfficialTopN) break;
                                if (result.status === 'rejected' || result.value?.status === 'skipped') {
                                    tasks.push(async () => {
                                        return {
                                            type: 'excluded',
                                            flight: returnBestList,
                                            reason: 'excluded_carrier',
                                            airlines: returnBestList.legs.map(flight => flight.airlineCode)
                                        };
                                    });
                                    continue
                                };
                                if (returnBestList.legs.some(item => flightParams.excludeCarriers.includes(item.airlineCode))) {
                                    tasks.push(async () => {
                                        return {
                                            type: 'excluded',
                                            flight: returnBestList,
                                            reason: 'excluded_carrier',
                                            airlines: returnBestList.legs.map(flight => flight.airlineCode)
                                        };
                                    });
                                    log.info('去程排除 ： ', returnBestList.legs.map(flight => flight.airlineCode))
                                    continue;
                                }
                                log.info('去程处理 :  ', returnBestList.legs.map(flight => flight.airlineCode))
                                rtItoa++;
                                bestPromises.push(async () => {
                                    try {
                                        const result = await engine.getBookingResult(flightParams, FlightList[j], returnList[y]);
                                        return {
                                            type: 'valid',
                                            data: result,
                                            flight: returnBestList
                                        };
                                    } catch (error) {
                                        return {
                                            type: 'error',
                                            error: error,
                                            flight: returnBestList
                                        };
                                    }
                                })
                            }
                            // let finalresult =  await processWithConcurrency(bestPromises)
                            // return finalresult.filter(item => item.status === "fulfilled" && item.value?.type === "valid").map(item => item.value)
                            return await processWithConcurrency(bestPromises)
                        }

                        const bookingbestResults = await deal_with(AllFlightList, returnBestList)
                        const bookingcommonResults = await deal_with(AllFlightList, returnCommonLists)
                        for (const bookingbestResult of bookingbestResults) {
                            if (bookingbestResult.status === 'fulfilled' && bookingbestResult.value.type === 'valid') {
                                const result = bookingbestResult.value.data;
                                for (const channelPrice of result.data.channelPrices) {
                                    // console.log('-------------------第一次best第二次best内部数据-------------------', channelPrice.name);
                                    channels.add(channelPrice.name);
                                }
                                rtBookingList.push(result.text);
                                resList.push(result.data);
                            }
                        }
                        for (const bookingcommonResult of bookingcommonResults) {
                            if (bookingcommonResult.status === 'fulfilled' && bookingcommonResult.value.type === 'valid') {
                                const result = bookingcommonResult.value.data;
                                for (const channelPrice of result.data.channelPrices) {
                                    // console.log('-------------------第一次best第二次best内部数据-------------------', channelPrice.name);
                                    channels.add(channelPrice.name);
                                }
                                rtBookingList.push(result.text);
                                resList.push(result.data);
                            }
                        }
                        toRes.push(returnData);
                    }
                }
            }

            await first_page_get_data(bestFlightList)
            await first_page_get_data(commonFlights)
        }
    } catch (e) {
        if (e instanceof TimeoutError) {
            res.channels = Array.from(channels);
            res.functionCallCount = engine.functionCallCount

            return res;
        }
        throw e
    }

    res.channels = Array.from(channels);
    res.functionCallCount = engine.functionCallCount
    return res;

}

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}